//import freemarker.template.Configuration;
import com.zaijiansunwukong.gen.model.Column;
import com.zaijiansunwukong.gen.model.Table;
import com.zaijiansunwukong.gen.util.DbUtils;
import com.zaijiansunwukong.gen.util.FreemarkerUtils;
import org.apache.commons.io.FileUtils;
import org.junit.Test;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* 注意事项： 1.请务必保证code表type字段的值和其他表中相应的字段名完全保持一致，否则jsp页面无法识别是否在前台生成combobox
* 2.请务必保证menu表中的url字段值后缀和表名完全相同，否则jsp页面无法正常生成请求url地址
* 3.如果code表有对应需要在字段comment中加入" 数据字典"
*
* @author wonderX
*
*/

//@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(locations = { "classpath:spring/spring-service-test.xml", "classpath:spring/spring-codegen.xml" })
public class CodeGenerator {

//	@Autowired
//	@Qualifier("freeMarkerConfigurationForCodegen")
//	Configuration configuration;

	Connection conn;

	@Test
	public void start() throws IOException {
		conn = DbUtils.getConnection("oracle.jdbc.driver.OracleDriver"
				,"jdbc:oracle:thin:@192.168.0.31:1521/orcl"
				,"ZJDXUSER"
				,"ZJDXUSER");

		// model名请务必使用驼峰命名法，首字母必须小写；传null代表生成所有表，传model名代表只生成某个model相关文件
		String taleName= "sbt_docmain";//表名
		String model = DbUtils.convent2Camel(taleName);// 实体对象的名称
		String filePath = "d:/codeGenerator/";
		generate(model, filePath);
	}

	/**
	 * 定义变量
	 *
	 * @return
	 */
	private Map<String, Object> getConfig(Table table) {
		Map<String, Object> data = new HashMap<String, Object>();
		data.put("org", "com");
		data.put("project", "zaijiansunwukong");

		data.put("modelName", DbUtils.convent2Camel(table.getTableName()));
		data.put("tableName", table.getTableName());
		data.put("modelComment", table.getComment());
		data.put("modelColumns", getColumns(table));
		// data.put("modelRequestUrl", getRequestUrl(table.getTableName()));
		return data;
	}

	/**
	 * 定义要生成的Template类型和文件类型
	 *
	 * @return
	 */
	private Map<String, String> getTemplateType() {
		Map<String, String> templateTypes = new HashMap<String, String>();
		templateTypes.put("Model", "java");
		templateTypes.put("Controller", "java");
		templateTypes.put("Service", "java");
		templateTypes.put("ServiceImpl", "java");
		templateTypes.put("Dao", "java");
		templateTypes.put("DaoImpl", "java");
//		templateTypes.put("Jsp", "jsp");
		return templateTypes;
	}

	/**
	 * 获取一个或多个模型的Template
	 *
	 * @param modelName
	 * @throws java.io.IOException
	 */
	public void generate(String modelName, String filePath) throws IOException {

		List<Table> tables = DbUtils.getTables(conn, modelName);
		for (Table table : tables) {
			createSource(table, filePath);
		}
		DbUtils.close(conn);
	}

	/**
	 * 生成文件
	 *
	 * @param table
	 * @param filePath
	 * @throws java.io.IOException
	 */
	public void createSource(Table table, String filePath) throws IOException {
		Map<String, Object> data = getConfig(table);
		String tableName = table.getTableName();

		for (Map.Entry<String, String> templateTypeMap : getTemplateType().entrySet()) {
			// 模板类型
			String templateType = templateTypeMap.getKey();
			// 模板对应文件类型
			String fileType = templateTypeMap.getValue();

			String className = DbUtils.convent2Camel(tableName);
			if (templateType.contains("Jsp")) {
				className = StringUtils.uncapitalize(className);
			} else {
				className = StringUtils.capitalize(className);
			}

			String src = FreemarkerUtils.processTemplate(templateType + ".ftl", data);

			File folder = new File(filePath, templateType);
			if (templateType.contains("Model") || templateType.contains("Jsp")) {
				templateType = "";
			}
			File file = new File(folder, className + templateType + "." + fileType);

			FileUtils.write(file, src, "utf-8");
		}
	}

	/**
	 * 得到处理后的Colums
	 *
	 * @param table
	 * @return
	 */
	private List<Column> getColumns(Table table) {
		return checkComboboxFlagClearComment(table);
	}

	/**
	 * 检查Table中column的字段在jsp页面显示时是否需要设置成combobox，如果需要则将Combobox设置为true
	 * 清洗comment的多余注释
	 *
	 * @param table
	 * @return
	 */
	private List<Column> checkComboboxFlagClearComment(Table table) {

		List<Column> columns = table.getColumns();
		for (Column column : columns) {
			String comment = column.getComment();
			column.setIsCombobox("false");
			if (isCombobox(comment)) {
				column.setIsCombobox("true");
				column.setCodeName(getCodeName(comment));
			}
			String clearComment = clearComment(comment);
			column.setComment(clearComment);
		}
		return columns;
	}

	private boolean isCombobox(String comment) {
		if (comment.contains("数据字典")) {
			return true;
		}
		return false;
	}

	/**
	 * 清洗comment
	 * 有些comment包含一些额外注释，需要清洗掉
	 *
	 * @param comment
	 * @return
	 */
	private String clearComment(String comment) {
		if (comment.contains(" ")) {
			comment = comment.substring(0, comment.indexOf(" "));
		}
		return comment;
	}

	/**
	 * 获取code的名称
	 *
	 * @param comment
	 * @return
	 */
	private String getCodeName(String comment) {
		if (comment.contains("数据字典")) {
			comment = comment.substring(comment.indexOf("数据字典"), comment.length() - 1).trim();
			return comment;
		}
		return null;
	}

}
